package com.example.springbootshiro.shiro;


import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.example.springbootshiro.security.RetryLimitHashedCredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);

         /*配置过滤器链:配置项目中url对应拦截规则
         等号左侧：url请求     所有url
         等号右侧：指定使用哪个过滤器（一般写简称）
         authc：表单认证过滤器：访问某些url,必须要求当前用户登陆后才能访问。
         anon:匿名过滤器：访问某些url不需要认证也不需要有权限就可以访问
         perms:权限授权过滤器。访问某些url需要当前用户有某个权限
         roles:角色授权过滤器。访问某些url需要当前用户有某个角色*/
        Map<String, String> filterMap = new HashMap<>();
        filterMap.put("/logout", "logout");
        filterMap.put("/**", "authc");
        filterMap.put("/static/**", "anon");
        filterMap.put("/static/**/*", "anon");
        filterMap.put("/toLogin", "anon");
        filterMap.put("/login", "anon");
        //filterMap.put("/office/*", "anon");
        filterMap.put("/user/**", "perms[user:admin]");
        //filterMap.put("/update", "perms[user:update]");
        bean.setFilterChainDefinitionMap(filterMap);

        bean.setLoginUrl("/toLogin");
        bean.setUnauthorizedUrl("/logout");
        return bean;
    }


    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm, @Qualifier("sessionManager") DefaultWebSessionManager sessionManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSessionManager(sessionManager);
        securityManager.setRealm(shiroRealm);
        return securityManager;
    }

    @Bean(name = "cacheManagers")
    public EhCacheManager cacheManagers(){
        EhCacheManager ehCacheManager= new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return ehCacheManager;
    }

    @Bean(name = "retryLimitHashedCredentialsMatcher")
    public RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher(){
        RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher =new RetryLimitHashedCredentialsMatcher();
        retryLimitHashedCredentialsMatcher.setCacheManager(cacheManagers());
        retryLimitHashedCredentialsMatcher.setHashAlgorithmName("SHA-256");
        retryLimitHashedCredentialsMatcher.setHashIterations(2);
        retryLimitHashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        return retryLimitHashedCredentialsMatcher;
    }


    @Bean(name = "sessionManager")
    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }


    @Bean(name = "shiroRealm")
    public ShiroRealm getShiroRealm(HashedCredentialsMatcher retryLimitHashedCredentialsMatcher){
        ShiroRealm shiroRealm=new ShiroRealm();
        shiroRealm.setAuthorizationCachingEnabled(false);
        shiroRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher);
        return shiroRealm;
    }

    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }


}
